/**
 * yckgou-util
 * @(#) FreeMarkerUtil.java 2012 2012-7-24 下午2:29:00
 * 
 * Copyright 2011 Chengdu Sunsharp Science & Techniques, Inc. All rights reserved.
 */
package com.huyanqi.core.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * <p>Title: FreeMarkerUtil.java</p>
 * 
 * <p>Description: 自动生成DAO Service</p>
 * 
 * <p>Datetime: 2012-7-24 下午2:29:00</p>
 *
 * @company 成都映潮科技有限公司
 * 
 * @author <a href="mailto:liwei@sunsharp.cn">ripper</a>
 *
 */
public class FreeMarkerUtil {
	private Configuration cfg;  
	/**
	 * 这里定义你的java工作空间
	 */
	private String workspace="F:\\JavaWorkSpace";
	
    public void init() throws Exception {  
        // 初始化FreeMarker配置  
        // 创建一个Configuration实例  
        cfg = new Configuration();  
        // 设置FreeMarker的模版文件位置  
        cfg.setDirectoryForTemplateLoading(new File(  
        		workspace+"/huyanqi/huyanqi-module/huyanqi-backWar/src/main/resources/template"));  
    }
    /**
     * 预处理
     * @param hf
     * @param entity_name 实体名 如：Item
     * @throws Exception
     */
    public void process(FreeMarkerUtil hf,String entity_name) throws Exception {  
    	  
        Map<String,String> root = new HashMap<String,String>();  

        root.put("entity_name", entity_name);  
        //生成DAO
        String projectPath = workspace+"/huyanqi/huyanqi-module/huyanqi-dao-interface/";    
        String fileName =  entity_name + "DAO.java";    
        String savePath = "src/main/java/com/huyanqi/dao/";    
        Template template = cfg.getTemplate("IDAO.ftl");    
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
  
        //生成DAOImpl
        projectPath = workspace+"/huyanqi/huyanqi-module/huyanqi-dao/";
        fileName = entity_name + "DAOImpl.java";  
        savePath = "src/main/java/com/huyanqi/dao/impl/";  
        template = cfg.getTemplate("IDAOImpl.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
        
        //生成Service
        projectPath = workspace+"/huyanqi/huyanqi-module/huyanqi-service-interface/";
        fileName = entity_name + "Service.java";  
        savePath = "src/main/java/com/huyanqi/service/";  
        template = cfg.getTemplate("IService.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
  
        //生成ServiceImpl
        projectPath = workspace+"/huyanqi/huyanqi-module/huyanqi-service/";
        fileName = entity_name + "ServiceImpl.java";  
        savePath = "src/main/java/com/huyanqi/service/impl/";  
        template = cfg.getTemplate("IServiceImpl.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
        
        
        
//        //生成Rest Service
//        projectPath = workspace+"/yckgou/yckgou-modules/yckgou-cms-module/yckgou-cms-front-rest-interface/";
//        fileName = entity_name + "RestService.java";  
//        savePath = "src/main/java/com/yingchao/kgou/cms/front/rest/service/";  
//        template = cfg.getTemplate("IRestService.ftl");  
//        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
//  
//        //生成Rest ServiceImpl
//        projectPath = workspace+"/yckgou/yckgou-modules/yckgou-cms-module/yckgou-cms-front-rest/";
//        fileName = entity_name + "RestServiceImpl.java";  
//        savePath = "src/main/java/com/yingchao/kgou/cms/front/rest/service/impl/";  
//        template = cfg.getTemplate("IRestServiceImpl.ftl");  
//        hf.buildTemplate(root, projectPath, savePath, fileName, template); 
        
        //生成Rest Service
//        projectPath = workspace+"/yckgou/yckgou-modules/ycmc-module/ycmc-model/ycmc-rest-interface/";
//        fileName = entity_name + "RestService.java";  
//        savePath = "src/main/java/com/yingchao/ycmc/front/rest/service/";  
//        template = cfg.getTemplate("IRestService.ftl");  
//        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
//  
//        //生成Rest ServiceImpl
//        projectPath = workspace+"/yckgou/yckgou-modules/ycmc-module/ycmc-model/ycmc-rest/";
//        fileName = entity_name + "RestServiceImpl.java";  
//        savePath = "src/main/java/com/yingchao/ycmc/front/rest/service/impl/";  
//        template = cfg.getTemplate("IRestServiceImpl.ftl");  
//        hf.buildTemplate(root, projectPath, savePath, fileName, template);
  
      /*  //生成DAO
        String projectPath = workspace+"/yckgou/yckgou-modules/yckgou-dao-interface/";    
        String fileName =  entity_name + "DAO.java";    
        String savePath = "src/main/java/com/yingchao/kgou/dao/";    
        Template template = cfg.getTemplate("IDAO.ftl");    
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
  
        //生成DAOImpl
        projectPath = workspace+"/yckgou/yckgou-modules/yckgou-dao/";
        fileName = entity_name + "DAOImpl.java";  
        savePath = "src/main/java/com/yingchao/kgou/dao/impl/";  
        template = cfg.getTemplate("IDAOImpl.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
        
        //生成Service
        projectPath = workspace+"/yckgou/yckgou-modules/yckgou-service-interface/";
        fileName = entity_name + "Service.java";  
        savePath = "src/main/java/com/yingchao/kgou/service/";  
        template = cfg.getTemplate("IService.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
  
        //生成ServiceImpl
        projectPath = workspace+"/yckgou/yckgou-modules/yckgou-service/";
        fileName = entity_name + "ServiceImpl.java";  
        savePath = "src/main/java/com/yingchao/kgou/service/impl/";  
        template = cfg.getTemplate("IServiceImpl.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
        
        //生成Rest Service
        projectPath = workspace+"/yckgou/yckgou-modules/yckgou-cms-module/yckgou-cms-front-rest-interface/";
        fileName = entity_name + "RestService.java";  
        savePath = "src/main/java/com/yingchao/kgou/cms/front/rest/service/";  
        template = cfg.getTemplate("IRestService.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  
  
        //生成Rest ServiceImpl
        projectPath = workspace+"/yckgou/yckgou-modules/yckgou-cms-module/yckgou-cms-front-rest/";
        fileName = entity_name + "RestServiceImpl.java";  
        savePath = "src/main/java/com/yingchao/kgou/cms/front/rest/service/impl/";  
        template = cfg.getTemplate("IRestServiceImpl.ftl");  
        hf.buildTemplate(root, projectPath, savePath, fileName, template);  */
  
    }  
    /**
     * 生成文件
     * @param root
     * @param projectPath
     * @param savePath
     * @param fileName
     * @param template
     */
    public void buildTemplate(Map<String,String> root, String projectPath, String savePath,  
            String fileName, Template template) {  
        String realFileName = projectPath + savePath + fileName;  
        File file=new File(realFileName);
        if(file.exists()){
        	System.out.println("文件："+fileName+"已存在");
        	return ;
        }
        String realSavePath = projectPath + savePath;  
  
        File newsDir = new File(realSavePath);  
        if (!newsDir.exists()) {  
            newsDir.mkdirs();  
        }  
  
        try {  
            // SYSTEM_ENCODING = "UTF-8";  
            Writer out = new OutputStreamWriter(new FileOutputStream(  
                    realFileName), Constants.SYSTEM_ENCODING);  
  
            template.process(root, out);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
  
    }  
    /**
     * 得到数据库的表名和对应的字段名
     * @return
     */
    public Map<String,List<String>> getTablesList(String driver,String url,String user,String password){
    	try {
    		Map<String,List<String>> map = new HashMap<String,List<String>>();
			  Class.forName(driver);
			  // 获取链接
			  Connection connection = DriverManager.getConnection(url, user, password);
			  String currentCatalog=connection.getCatalog();
			  ResultSet resultSet = connection.getMetaData().getTables(currentCatalog, null, null, new String[]{"TABLE"});
			  ResultSet rs = null;
			  while(resultSet.next()){
                String tableName=resultSet.getObject(3).toString();
                rs = connection.getMetaData().getColumns(currentCatalog, null, tableName, null);
                List<String> list = new ArrayList<String>();
                while(rs.next()){
                	list.add(rs.getString(4)+":"+rs.getString("IS_AUTOINCREMENT")+":"+rs.getString("DATA_TYPE"));
                }
                map.put(tableName, list);
			  } 
			  rs.close();
			  resultSet.close();
			  connection.close();
			  return map;
		} catch (Exception e) {
			e.printStackTrace();
		}
    	return null;
    }
    
    public void generateEntity(String projectPath,String savePath,Map<String,List<String>> map){
    	try {
    		String fileName;
    		for(Map.Entry<String, List<String>> entry:map.entrySet()){
    			String tableName = entry.getKey();
    			fileName = tableName.substring(tableName.indexOf("_")+1);
    			if(fileName.contains("_")){
    				String names[] = fileName.split("_");
    				for (int i =0;i<names.length;i++) {
						if(i==0){
							fileName = names[i].substring(0,1).toUpperCase()+names[i].substring(1);
							continue;
						}
						fileName += names[i].substring(0,1).toUpperCase()+names[i].substring(1);
					}
    			}else{
    				fileName = fileName.substring(0,1).toUpperCase()+fileName.substring(1);
    			}
    			File file = new File(projectPath+savePath+fileName+".java");
    			if(file.exists()){
    				System.err.println("entity:"+fileName+"已存在！");
    				continue;
    			}
    			StringBuilder sb = new StringBuilder();
    			sb.append("package "+savePath.substring(14,savePath.length()-1).replaceAll("/", ".")+";\r\n");
    			sb.append("\r\n");
    			sb.append("import javax.persistence.Basic;\r\n");
    			sb.append("import javax.persistence.Column;\r\n");
    			sb.append("import javax.persistence.Entity;\r\n");
    			sb.append("import javax.persistence.FetchType;\r\n");
    			sb.append("import javax.persistence.GeneratedValue;\r\n");
    			sb.append("import javax.persistence.GenerationType;\r\n");
    			sb.append("import javax.persistence.Id;\r\n");
    			sb.append("import javax.persistence.Table;\r\n");
    			sb.append("import javax.persistence.Temporal;\r\n");
    			sb.append("import javax.persistence.TemporalType;\r\n");
    			sb.append("import javax.xml.bind.annotation.XmlAccessType;\r\n");
    			sb.append("import javax.xml.bind.annotation.XmlAccessorType;\r\n");
    			sb.append("import javax.xml.bind.annotation.XmlElement;\r\n");
    			sb.append("import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;\r\n");
    			sb.append("import com.yingchao.kgou.core.BaseDomainObject;\r\n");
    			sb.append("import com.yingchao.kgou.util.JaxbCalendarSerializer;\r\n");
    			sb.append("import java.util.Calendar;\r\n");
    			sb.append("\r\n");
    			sb.append("@Entity\r\n");
    			sb.append("@Table(name = \""+tableName+"\")\r\n");
    			sb.append("@XmlAccessorType(XmlAccessType.FIELD)\r\n");
    			sb.append("public class "+fileName+" extends BaseDomainObject {\r\n");
    			List<String> list = entry.getValue();
    			for (String str : list) {
					String string[] = str.split(":");
					String columnName = string[0];//列名
					String oldColumn = columnName;
					String isAuto = string[1];//是否自增
					Integer type = Integer.valueOf(string[2]);
					if(isAuto.equals("YES")){
						sb.append("\t@GeneratedValue(strategy = GenerationType.IDENTITY)\r\n");
						sb.append("\t@Id\r\n");
						sb.append("\t@Column(name=\""+columnName+"\",nullable=false)\r\n");
					}else{
						sb.append("\t@Column(name=\""+columnName+"\")\r\n");
					}
					sb.append("\t@XmlElement\r\n");
					sb.append("\t@Basic(fetch=FetchType.EAGER)\r\n");
					if(columnName.contains("_")){
						String names[] = columnName.split("_");
	    				for (int i =0;i<names.length;i++) {
							if(i==0){
								columnName = names[i].substring(0,1).toUpperCase()+names[i].substring(1);
								oldColumn = names[i];
								continue;
							}
							columnName += names[i].substring(0,1).toUpperCase()+names[i].substring(1);
							oldColumn += names[i].substring(0,1).toUpperCase()+names[i].substring(1);
						}
	    			}else{
	    				columnName = columnName.substring(0,1).toUpperCase()+columnName.substring(1);
	    			}
					String newName = " ";
					String newType = " ";
					switch(type){
					case Types.BIGINT:
						newType = "Long";
						newName = "Long "+oldColumn;
						sb.append("\tprivate Long "+oldColumn+";\r\n");
						break;
					case Types.SMALLINT:
					case Types.INTEGER:
						newType = "Integer";
						newName = "Integer "+oldColumn;
						sb.append("\tprivate Integer "+oldColumn+";\r\n");
						break;
					case Types.TINYINT:
					case Types.BOOLEAN:
					case Types.BIT:
						newType = "Boolean";
						newName = "Boolean "+oldColumn;
						sb.append("\tprivate Boolean "+oldColumn+";\r\n");
						break;
					case Types.VARCHAR:
					case Types.LONGVARCHAR:
					case Types.LONGNVARCHAR:
						newType = "String";
						newName = "String "+oldColumn;
						sb.append("\tprivate String "+oldColumn+";\r\n");
						break;
					case Types.DATE:
					case Types.TIMESTAMP:
					case Types.TIME:
						newType = "Calendar";
						newName = "Calendar "+oldColumn;
						sb.append("\t@XmlJavaTypeAdapter(JaxbCalendarSerializer.class)\r\n");
						sb.append("\t@Temporal(TemporalType.TIMESTAMP)\t\n");
						sb.append("\tprivate Calendar "+oldColumn+";\r\n");
						break;
					case Types.DOUBLE:
						newType = "Double";
						newName = "Double "+oldColumn;
						sb.append("\tprivate Double "+oldColumn+";\r\n");
						break;
					case Types.FLOAT:
						newType = "Float";
						newName = "Float "+oldColumn;
						sb.append("\tprivate Float "+oldColumn+";\r\n");
						break;
					}
					sb.append("\r\n");
					String setter = columnName.substring(0,1).toUpperCase()+columnName.substring(1);
					sb.append("\tpublic void set"+setter+"("+newName+") {\r\n");
					sb.append("\t\tthis."+oldColumn+" = "+oldColumn+";\r\n");
					sb.append("\t}");
					sb.append("\r\n");
					sb.append("\tpublic "+newType+" get"+setter+"() {\r\n");
					sb.append("\t\treturn "+oldColumn+";\r\n");
					sb.append("\t}\r\n");
					sb.append("\r\n");
				}
    			sb.append("}");
    			FileWriter fw = new FileWriter(file);
    			fw.append(sb.toString());
    			fw.close();
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    //注意:生成后的文件要刷新一下才显示的出来
	public static void main(String[] args) throws Exception{
		 FreeMarkerUtil hf = new FreeMarkerUtil();
		 hf.init();
		 hf.process(hf,"Shop"); //Ceshi是需生成的实体的名字。
		Map<String, List<String>> map = hf.getTablesList("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/tfa", "root", "huyanqi");
		hf.generateEntity("F:/JavaWorkSpace/huyanqi/huyanqi-module/huyanqi-entity/", "src/main/java/com/huyanqi/entity/", map);
	}

}
